package cn.huiyunche.base.service.interfaces.impl;

import cn.huiyunche.base.service.framework.utils.BaiDuMapUtils;
import cn.huiyunche.base.service.framework.utils.GDMapUtils;
import cn.huiyunche.base.service.interfaces.BCitiesDistanceService;
import cn.huiyunche.base.service.interfaces.GDMapService;
import cn.huiyunche.base.service.vo.BaiDuDistance;
import cn.huiyunche.base.service.vo.DistanceVo;
import cn.huiyunche.base.service.vo.GDMapResult;
import cn.huiyunche.tools.basic.exceptions.BusinessException;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * 地图工具接口实现类
 *
 * @author houjianhui
 */
@Service
public class GDMapServiceImpl implements GDMapService {

    private static final Logger logger = LoggerFactory.getLogger(GDMapServiceImpl.class);

    @Autowired
    private BCitiesDistanceService citiesDistanceService;

    public BigDecimal distance(String departCode, String departAddr, String receiptCode, String receiptAddr) throws Exception {
        logger.info("distance params : {}, {}, {}, {}", departCode, departAddr, receiptCode, receiptAddr);
        if (StringUtils.isBlank(departAddr)) {
            logger.error("distance departAddr is null");
            throw new BusinessException("departAddr为空！");
        }
        if (StringUtils.isBlank(receiptAddr)) {
            logger.error("distance receiptAddr is null");
            throw new IllegalArgumentException("receiptAddr为空！");
        }

        //如果起始地编码和目的地编码相等且详细地址都为空的情况下运距等于0
        if (StringUtils.isNotBlank(departCode) && StringUtils.isNotBlank(receiptCode)) {
            if (departCode.equals(receiptCode)) {
                return BigDecimal.ZERO.setScale(2);
            }
        }

        //若已经存储的有则不需要重新计算城市之间的距离
        BigDecimal distance;
        if (StringUtils.isNotBlank(departCode) && StringUtils.isNotBlank(receiptCode)) {
            distance = citiesDistanceService.getDistanceByCitiesCode(departCode, receiptCode);
            if (null != distance) {
                return distance;
            }
        }

        double[] depart = GDMapUtils.addressToGPS(departAddr);
        double[] receipt = GDMapUtils.addressToGPS(receiptAddr);
        if (depart == null || receipt == null) {
            logger.error("distance depart|receipt is null");
            throw new BusinessException("获取经纬度失败！");
        }
        String startAddr = depart[0] + "," + depart[1];
        String endAddr = receipt[0] + "," + receipt[1];
        String res = GDMapUtils.distance(startAddr, endAddr, "JSON");
        JSONObject obj = JSONObject.parseObject(res);
        GDMapResult result = JSONObject.toJavaObject(obj, GDMapResult.class);
        List<DistanceVo> distanceVos = result.getResults();
        if (CollectionUtils.isNotEmpty(distanceVos)) {
            distance = new BigDecimal(distanceVos.get(0).getDistance()).divide(new BigDecimal(1000));

            //depacode:610102 陕西省西安市新城区 destcode:654024 新疆伊犁州巩留县
            //如果起始地编码和目的地编码不同查询返回运距是0（{"status":"1","info":"OK","infocode":"10000","results":[{"origin_id":"1","dest_id":"1","distance":"0","duration":"0","info":"未知错误"}]}） 则调用百度查询运距
            if (distance.compareTo(BigDecimal.ZERO) == 0) {
                distance = this.distanceByBaiDu(departCode, departAddr, receiptCode, receiptAddr);
            }

            if (StringUtils.isNotBlank(departCode) && StringUtils.isNotBlank(receiptCode) && !(0 == distance.compareTo(BigDecimal.ZERO))) {
                citiesDistanceService.add(departCode, receiptCode, distance);
            }
            return distance;
        }
        return BigDecimal.ZERO.setScale(2);
    }

    public BigDecimal distanceByBaiDu(String departCode, String departAddr, String receiptCode, String receiptAddr) throws Exception {
        logger.info("distanceByBaiDu params : {}, {}, {}, {}", departCode, departAddr, receiptCode, receiptAddr);
        if (StringUtils.isBlank(departAddr)) {
            logger.error("distanceByBaiDu departAddr is null");
            throw new BusinessException("departAddr为空！");
        }
        if (StringUtils.isBlank(receiptAddr)) {
            logger.error("distanceByBaiDu receiptAddr is null");
            throw new IllegalArgumentException("receiptAddr为空！");
        }
        double[] depart = BaiDuMapUtils.addressToGPS(departAddr);
        double[] receipt = BaiDuMapUtils.addressToGPS(receiptAddr);
        if (depart == null || receipt == null) {
            logger.error("distanceByBaiDu depart|receipt is null");
            throw new BusinessException("获取经纬度失败！");
        }
        String startAddr = depart[1] + "," + depart[0];
        String endAddr = receipt[1] + "," + receipt[0];
        String res = BaiDuMapUtils.distance(startAddr, endAddr, "JSON");
        Gson gson = new Gson();
        BaiDuDistance dis = gson.fromJson("{" + res + "}", BaiDuDistance.class);
        if (dis != null) {
            BigDecimal distance = BigDecimal.valueOf(dis.getDistance().getValue()).divide(BigDecimal.valueOf(1000));
            if (StringUtils.isNotBlank(departCode) && StringUtils.isNotBlank(receiptCode)) {
                citiesDistanceService.add(departCode, receiptCode, distance);
            }
            return distance;
        }
        return BigDecimal.ZERO.setScale(2);
    }

    public String getLongitudeAndLatitudeByAddress(String address) throws Exception {
        if (StringUtils.isBlank(address)) {
            logger.error("getLongitudeAndLatitudeByAddress address is null");
            throw new BusinessException("地址为空！");
        }
        double[] longitudeAndLatitude = BaiDuMapUtils.addressToGPS(address);
        return new StringBuffer(String.valueOf(longitudeAndLatitude[0])).append(",")
                .append(String.valueOf(longitudeAndLatitude[1])).toString();
    }

    public BigDecimal getDistanceByLongitudeAndLatitude(String deptLongitudeAndLatitude,
                                                        String destLongitudeAndLatitude) {
        if (StringUtils.isBlank(deptLongitudeAndLatitude)) {
            logger.error("getDistanceByLongitudeAndLatitude deptLongitudeAndLatitude is null");
            throw new BusinessException("destLongitudeAndLatitude is can not be null！");
        }
        if (StringUtils.isBlank(destLongitudeAndLatitude)) {
            logger.error("getDistanceByLongitudeAndLatitude destLongitudeAndLatitude is null");
            throw new BusinessException("destLongitudeAndLatitude为空！");
        }
        String res = GDMapUtils.distance(deptLongitudeAndLatitude, destLongitudeAndLatitude, "JSON");
        JSONObject obj = JSONObject.parseObject(res);
        GDMapResult result = JSONObject.toJavaObject(obj, GDMapResult.class);
        List<DistanceVo> distanceVos = result.getResults();
        if (CollectionUtils.isNotEmpty(distanceVos)) {
            return new BigDecimal(distanceVos.get(0).getDistance()).divide(new BigDecimal(1000)).setScale(4,
                    BigDecimal.ROUND_UP);
        }
        return BigDecimal.ZERO.setScale(4);
    }

}
